/*
 * @Date: 2023-03-17 15:41:09
 * @LastEditors: Chuying
 * @LastEditTime: 2023-04-01 17:56:16
 * @Description:
 */
import { User } from './entities/user.entity';
import { UserInfo } from './entities/user_info.entity';
import { Injectable, HttpException, HttpStatus } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { CreateUserDto } from './dto/create-user.dto';
import { UpdateUserDto } from './dto/update-user.dto';
import { UserInfoDTO } from './dto/user-info.dto';
import { Repository, EntityManager } from 'typeorm';
import * as bcrypt from 'bcryptjs';
import * as dayjs from 'dayjs';
import { FollowDto } from './dto/follow-dto';
import { Friend } from './entities/friend.entity';

@Injectable()
export class UserService {
  constructor(
    @InjectRepository(User) private readonly userRepository: Repository<User>,
    @InjectRepository(UserInfo) private readonly userInfo: Repository<UserInfo>,
    @InjectRepository(Friend) private readonly friendRepo: Repository<Friend>,
  ) {}
  responseFormat(result = undefined) {
    return {
      status: 0,
      message: 'Success',
      result,
    };
  }

  async follow(followDto: FollowDto, type: 'update' | 'cancel') {
    const { user, target } = followDto;
    console.log('follow 查找', followDto);

    const checkUser = await this.userRepository.findOne({
      where: { id: user },
    });

    const checkFollow = await this.userRepository.findOne({
      where: { id: target },
    });

    if (!checkUser || !checkFollow) {
      throw new HttpException('用户不存在', HttpStatus.NOT_FOUND);
    }

    const followRecord = await this.friendRepo.findOne({
      where: { user: { id: user }, follow: { id: target } },
      relations: ['user', 'follow'],
    });
    console.log('followRecord', followRecord);
    if (followRecord) {
      // 已存在该关系
      const result = this.friendRepo.merge(followRecord, {
        state: type === 'update' ? 1 : 0,
      });
      console.log('has reco');
      this.friendRepo.save(result);
    } else {
      const newRecord = new Friend();
      newRecord.user = checkUser;
      newRecord.follow = checkFollow;
      newRecord.state = 1;
      console.log('creat a new reco');
      this.friendRepo.save(newRecord);
    }
  }

  async create(createUserDto: CreateUserDto) {
    const { username, password } = createUserDto;
    if (!username) {
      throw new HttpException('请输入用户名', HttpStatus.ACCEPTED);
    } else if (!password) {
      throw new HttpException('请输入密码', HttpStatus.ACCEPTED);
    }

    const existUser = await this.userRepository.findOne({
      where: { username },
    });
    if (existUser) {
      throw new HttpException('用户名已存在', HttpStatus.CONFLICT);
    }

    createUserDto.password = bcrypt.hashSync(password, 10);
    // 副表新增
    const mInfo = new UserInfo();
    mInfo.real_name = '无往不利大前端';
    mInfo.avatar =
      'http://simg01.gaodunwangxiao.com/uploadimgs/tmp/upload/202304/13/b756e_20230413112045.png';
    mInfo.gender = '';
    mInfo.phone = '';
    await this.userInfo.save(mInfo);

    // 主表新增
    const muser = new User();
    muser.username = createUserDto.username;
    muser.password = createUserDto.password;
    // 绑定关联
    muser.userInfo = mInfo;
    await this.userRepository.save(muser);
    return 'Success';

    // this.userRepository.manager.transaction(async (manage) => {
    //   createUserDto.password = bcrypt.hashSync(password, 10);
    //   // 副表新增
    //   let mInfo = new UserInfo();
    //   mInfo.real_name = '无往不利大前端';
    //   mInfo.avatar =
    //     'http://simg01.gaodunwangxiao.com/uploadimgs/tmp/upload/202304/13/b756e_20230413112045.png';
    //   mInfo.gender = '';
    //   mInfo.phone = '';
    //   const res = await manage.save(UserInfo, mInfo);

    //   // 主表新增
    //   let muser = new User();
    //   muser.username = createUserDto.username;
    //   muser.password = createUserDto.password;
    //   // 绑定关联
    //   muser.userInfo = mInfo;
    //   const ret = await manage.save(User, muser);
    //   return 'Success';
    // });
    // throw new HttpException('创建失败', HttpStatus.CONFLICT);
  }

  async update(id: number, updateUserDto: UpdateUserDto) {
    const existUser = await this.userRepository.findOneBy({ id });
    if (!existUser) {
      throw new HttpException('用户名已存在', HttpStatus.CREATED);
    }
    const updatePost = this.userRepository.merge(existUser, updateUserDto);
    return this.userRepository.save(updatePost);
  }

  async findAll() {
    const res = await this.userRepository.find();
    return this.responseFormat(res);
  }

  async findOne(id: number) {
    const res = await this.userRepository.findOneBy({ id });
    return this.responseFormat(res);
  }

  async remove(id: number) {
    const res = await this.userRepository.delete(id);
    if (res.affected) {
      return this.responseFormat();
    }
    throw new HttpException('删除失败', HttpStatus.CREATED);
  }

  findLoginUser(username: string) {
    return this.userRepository.findOne({
      where: { username },
      select: ['id', 'username', 'password'],
    });
  }

  // 查询用户信息
  async findUserInfo(id: number) {
    const infoFromDb = await this.userRepository.findOne({
      //查询的时候如果需要联合查询需要增加 relations
      relations: ['userInfo'],
      where: { id },
    });
    // 查询关注者为当前userId的关注的人  ---- 正在关注的
    const followingList = await this.friendRepo.find({
      where: { user: { id }, state: 1 },
      relations: ['follow'],
    });
    // 查询被关注者为当前userId的关注者  ---- 粉丝
    const followerList = await this.friendRepo.find({
      where: { follow: { id }, state: 1 },
      relations: ['user'],
    });
    console.log('followerList', followerList);
    // 计算年龄，输出
    const age = dayjs().diff(dayjs(infoFromDb.userInfo.birth), 'year');
    const result = {
      ...infoFromDb.userInfo,
      age,
      id: infoFromDb.id,
      username: infoFromDb.username,
      followings: followingList
        .map((i: any) => i.follow)
        .filter((i) => i)
        .map((i) => ({ username: i.username, id: i.id })),
      followers: followerList
        .map((i: any) => i.follow)
        .filter((i) => i)
        .map((i) => ({ username: i.username, id: i.id })),
    };
    return result;
  }

  async changeInfo(info: UserInfoDTO, user: any) {
    // const existUser = await this.userInfo.findOne({
    //   where: { userId: user.userId },
    // });
    const res = await this.findUserInfo(user.userId);
    // console.log(existUser, '88888888');
    const update = this.userInfo.merge(res, info);
    return this.userInfo.save(update);
  }
}
